﻿using System.Web.Mvc;
using ManagedUIFlow.Model;

namespace ManagedUIFlow.Infrastructure.Commands.FlowActionHelpers
{
    public abstract class FlowController : Controller
    {
        public ManagedFlow ManagedFlow { get; set; }

        protected internal FlowActionResult State()
        {
            return new FlowActionResult(ManagedFlow, null);
        }

        protected internal FlowActionResult State<T>(T stateName)
        {
            return new FlowActionResult(ManagedFlow, stateName.ToString());
        }

        protected internal FlowActionResult State<T>(T stateName, FlowViewModel model)
        {
            if(model != null)
                ManagedFlow.ViewData.Model = model;

            return new FlowActionResult(ManagedFlow, stateName.ToString());
        }

        protected internal FlowActionResult State(FlowViewModel model)
        {
            if (model != null)
                ManagedFlow.ViewData.Model = model;

            return State();
        }

        public ManagedFlowDataDictionary FlowData
        {
            get
            {
                return ManagedFlow.FlowData;
            }
        }

        public ManagedFlowDataDictionary ConversationData
        {
            get
            {
                return ManagedFlow.ConversationData;
            }
        }
        
        /// <summary>
        /// Method called after the action method is invoked.
        /// </summary>
        /// <param name="filterContext" />Contains information about the current request and action.
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // check there is data in the Model
            //
            var baseFormViewModelType = typeof(FlowViewModel);
            if (filterContext.Controller.ViewData.Model != null)
            {
                // bit of reflection magic and get the types
                //
                var modelType = filterContext.Controller.ViewData.Model.GetType();

                // if the model type is derived from the base type then
                // we can set some properties.
                //

                if (baseFormViewModelType.IsAssignableFrom(modelType))
                {
                    // inject the value to the ViewData.Model property
                    //
                    modelType.GetProperty("Flowdata").SetValue(filterContext.Controller.ViewData.Model, FlowData, null);
                    modelType.GetProperty("ConversationData").SetValue(filterContext.Controller.ViewData.Model, ConversationData, null);
                }
            }
            else if(filterContext.Controller.ViewData.Model == null)
            {
                var model = new FlowViewModel()
                                {
                                    Flowdata = FlowData,
                                    ConversationData = ConversationData
                                };
                filterContext.Controller.ViewData.Model = model;
            }

            base.OnActionExecuted(filterContext);            
        }
    }
}